package network;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * 非阻塞
 * @author glogo
 *
 */
public class EchoServer2 {

	private int port = 8000;
	private ServerSocketChannel serverSocketChannel = null;
	private Selector selector;
	
	public EchoServer2() throws IOException{
		selector = Selector.open();
		serverSocketChannel = ServerSocketChannel.open();
		serverSocketChannel.socket().setReuseAddress(true);
		serverSocketChannel.configureBlocking(false);		//非阻塞模式
		serverSocketChannel.socket().bind(new InetSocketAddress(port));
	}
	
	public static void main(String[] args) throws IOException{
		new EchoServer2().service();
	}
	
	public void service(){
		try {
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
			while(selector.select() > 0){
				Set<SelectionKey> readyKeys = selector.selectedKeys();
				Iterator<SelectionKey> it = readyKeys.iterator();
				while(it.hasNext()){
					SelectionKey key = null;
					try{
						key = it.next();
						it.remove();
						//处理连接就绪事件
						if(key.isAcceptable()){
							ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
							SocketChannel socketChannel = ssc.accept();
							System.out.println(
									"接受到来自客户的连接：" + socketChannel.socket().getInetAddress() + ":" + socketChannel.socket().getPort());
							socketChannel.configureBlocking(false);	//socketChannel也要设置成非阻塞
							ByteBuffer buffer = ByteBuffer.allocate(1024);
							socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE,  buffer);
						}
						//处理读就绪事件
						if(key.isReadable()){
							receive(key);
						}
						//处理写就绪事件
						if(key.isWritable()){
							send(key);
						}
					}catch(IOException e){
						e.printStackTrace();
						try{
							if(key != null){
								key.cancel();
								key.channel().close();
							}
						}catch(IOException ee){ee.printStackTrace();}
					}
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void send(SelectionKey key) throws IOException{
		ByteBuffer buffer = (ByteBuffer) key.attachment();
		SocketChannel socketChannel = (SocketChannel) key.channel();
		buffer.flip();
		Charset charset = Charset.forName("UTF-8");
		String data = charset.decode(buffer).toString();
		if(data.indexOf("\r\n") == -1)	return;
		String outputData = data.substring(0, data.indexOf("\n") + 1);
		System.out.println(outputData);
		ByteBuffer outputBuffer = charset.encode("echo:" + outputData);
		while(outputBuffer.hasRemaining()){
			socketChannel.write(outputBuffer);
		}
		ByteBuffer temp = charset.encode(outputData);
		buffer.position(temp.limit());
		buffer.compact();
		if(outputData.equals("bye\r\n")){
			key.cancel();
			socketChannel.close();
			System.out.println("关闭与客户端的连接");
		}
	}

	private void receive(SelectionKey key) throws IOException{
		ByteBuffer buffer = (ByteBuffer) key.attachment();
		SocketChannel socketChannel = (SocketChannel) key.channel();
		ByteBuffer readBuff = ByteBuffer.allocate(32);
		socketChannel.read(readBuff);
		readBuff.flip();
		buffer.limit(buffer.capacity());	//防止溢出，其实这样做在这个程序中没有实际意义
		buffer.put(readBuff);
	}
	
	
	
}
